// EMERGENT GAME TECHNOLOGIES PROPRIETARY INFORMATION
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Emergent Game Technologies and may not 
// be copied or disclosed except in accordance with the terms of that 
// agreement.
//
//      Copyright (c) 1996-2008 Emergent Game Technologies.
//      All Rights Reserved.
//
// Emergent Game Technologies, Chapel Hill, North Carolina 27517
// http://www.emergent.net

#ifndef NITOBJECTLIST_H
#define NITOBJECTLIST_H

#include "GnMainLibType.h"
#include "GnRTLib.h"

#include "GnTListBase.h"
#include "GnTObjectAllocator.h"

// GnTObjectList is designed to hold compound objects efficiently. It
// is responsible for allocating and freeing the elements in the list. The
// interface does not support copy construction assignment of T directly.
// Instead, element access is provided via a pointer to the element.
// T is block allocated from a shared memory pool. The template class 
// requires that a default constructor for T exists, even if it does nothing.
//
// The pool uses some non-local static variables that must be declared using
// the GnAllocatorDeclareStatics macro. For example:
//   GnAllocatorDeclareStatics(T, size);
// where T is the template type T and size is the block size for the memory
// pool. To free this memory pool, use:
//   GnAllocatorShutdown(T);
// GnAllocatorShutdown assumes that any GnTObjectList<T> instances have been
// destroyed. Accessing a pre-existing GnTObjectList<T> after calling
// GnAllocatorShutdown(T) will cause a memory access violation. After calling
// GnAllocatorShutdown(T), new GnTObjectList<T> instances may be created, but
// of course they should be cleaned up with another call to
// GnAllocatorShutdown(T).
// 
// Remove and FindPos search for an element based on pointer equality. 
//
// Example of iteration from head to tail:
//
//   GnTObjectList<T> kList;
//   GnTListIterator kPos = kList.GetHeadPos();
//   while (kPos)
//   {
//       T* element = kList.GetNext(kPos);
//       <process element here>;
//   }

template <class T> class GnTObjectList :
    public GnTListBase<GnTObjectAllocator<T>, T>
{
public:
    virtual ~GnTObjectList();

    // Add/Insert functions return a pointer to a new object.
    // No constructor is called; data must be explicitly initialized.
    T* AddNewHead();
    T* AddNewTail();
    T* InsertNewBefore(GnTListIterator kPos, GnTListIterator& kNewIterator);
    T* InsertNewAfter(GnTListIterator kPos, GnTListIterator& kNewIterator);
    T* InsertNewBefore(GnTListIterator kPos);
    T* InsertNewAfter(GnTListIterator kPos);

    // Element access
    T* GetHead() const;
    T* GetTail() const;
    T* Get(GnTListIterator kPos) const;

    // Element access with iteration support
    T* GetNext(GnTListIterator& kPos) const;
    T* GetPrev(GnTListIterator& kPos) const;

    // Remove functions free the object but do not call the destructor.
    // If cleanup is required it must be done explicitly.
    void RemoveHead();
    void RemoveTail();
    void Remove(const T* element);
    void RemovePos(GnTListIterator& kPos);

    // Element search
    GnTListIterator FindPos(const T* element, 
        GnTListIterator kStart = 0) const;
    
protected:
    virtual GnTListItem<T>* NewItem();
    virtual void DeleteItem(GnTListItem<T>* pkItem);

};

//---------------------------------------------------------------------------
// Inline include
#include "GnTObjectList.inl"
//---------------------------------------------------------------------------

#endif // NITOBJECTLIST_H
